home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dtl
/
dt2dv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-28
|
55KB
|
2,490 lines
/* dt2dv - convert human-readable "DTL" file to DVI format
- this is intended to invert dv2dt version 0.5.*.
- version 0.5.3 - 16:54 GMT +11 Wed 1 March 1995
(this version uses fseek to move about in output DVI file)
- Geoffrey Tobin ecsgrt@luxor.latrobe.edu.au
- patch: Michal Tomczak-Jaegermann ntomczak@vm.ucs.ualberta.ca
- Reference: "The DVI Driver Standard, Level 0",
by The TUG DVI Driver Standards Committee.
Appendix A, "Device-Independent File Format".
*/
/* unix version; read from stdin, write to stdout, by default. */
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dtl.h"
/* maximum number of characters in a DTL input line */
#define MAXLINE 1024
/* input line */
typedef struct
{
size_t next; /* position in buf of next character to read */
size_t len; /* number of characters in buf */
size_t max; /* capacity of buf */
char * buf; /* line buffer */
} Line;
char linebuf[MAXLINE+1];
Line dtl_line = {0, 0, MAXLINE, linebuf};
/* a DTL token either is:
a quoted string (admitting an escape character),
or BCOM (if that is a nonempty string),
or ECOM (if that is a nonempty string),
or a string _not_ including ECOM_CHAR or space.
*/
/* maximum expected length of a DTL token */
#define MAXTOKLEN 255
typedef char Token[MAXTOKLEN+1];
typedef unsigned char Byte;
typedef char Boolean;
#define true 1
#define false 0
/* command prefixes */
typedef struct
{
Byte first_code;
char * name;
Boolean has_suffix;
Byte first_suffix, last_suffix;
} CmdPrefix;
CmdPrefix cmd_prefixes [] =
{
{0, SETCHAR, true, 0, 127},
{128, SET, true, 1, 4},
{132, SETRULE, false, 0, 0},
{133, PUT, true, 1, 4},
{137, PUTRULE, false, 0, 0},
{138, NOP, false, 0, 0},
{139, BOP, false, 0, 0},
{140, EOP, false, 0, 0},
{141, PUSH, false, 0, 0},
{142, POP, false, 0, 0},
{143, RIGHT, true, 1, 4},
{147, W, true, 0, 4},
{152, X, true, 0, 4},
{157, DOWN, true, 1, 4},
{161, Y, true, 0, 4},
{166, Z, true, 0, 4},
{171, FONTNUM, true, 0, 63},
{235, FONT, true, 1, 4},
{239, SPECIAL, true, 1, 4},
{243, FONTDEF, true, 1, 4},
{247, PRE, false, 0, 0},
{248, POST, false, 0, 0},
{249, POSTPOST, false, 0, 0},
{250, OPCODE, true, 250, 255}
};
/* cmd_prefixes[] */
/* table of command names */
typedef char * CmdTable [256];
CmdTable cmd_table;
/* operation's opcode, name, number of args, string of arguments. */
typedef struct
{
int code;
char * name;
int nargs;
char * args;
} op_info;
/* name of table, first opcode, last opcode, pointer to opcode info. */
typedef struct
{
char * name;
int first;
int last;
op_info * list;
} op_table;
/* Table for opcodes 128 to 170 inclusive. */
op_info op_info_128_170 [] =
{
{128, SET1, 1, "1"},
{129, SET2, 1, "2"},
{130, SET3, 1, "3"},
{131, SET4, 1, "-4"},
{132, SETRULE, 2, "-4 -4"},
{133, PUT1, 1, "1"},
{134, PUT2, 1, "2"},
{135, PUT3, 1, "3"},
{136, PUT4, 1, "-4"},
{137, PUTRULE, 2, "-4 -4"},
{138, NOP, 0, ""},
/* bop: not counting last argument, a signed address: */
{139, BOP, 10, "-4 -4 -4 -4 -4 -4 -4 -4 -4 -4"},
{140, EOP, 0, ""},
{141, PUSH, 0, ""},
{142, POP, 0, ""},
{143, RIGHT1, 1, "-1"},
{144, RIGHT2, 1, "-2"},
{145, RIGHT3, 1, "-3"},
{146, RIGHT4, 1, "-4"},
{147, W0, 0, ""},
{148, W1, 1, "-1"},
{149, W2, 1, "-2"},
{150, W3, 1, "-3"},
{151, W4, 1, "-4"},
{152, X0, 0, ""},
{153, X1, 1, "-1"},
{154, X2, 1, "-2"},
{155, X3, 1, "-3"},
{156, X4, 1, "-4"},
{157, DOWN1, 1, "-1"},
{158, DOWN2, 1, "-2"},
{159, DOWN3, 1, "-3"},
{160, DOWN4, 1, "-4"},
{161, Y0, 0, ""},
{162, Y1, 1, "-1"},
{163, Y2, 1, "-2"},
{164, Y3, 1, "-3"},
{165, Y4, 1, "-4"},
{166, Z0, 0, ""},
{167, Z1, 1, "-1"},
{168, Z2, 1, "-2"},
{169, Z3, 1, "-3"},
{170, Z4, 1, "-4"}
};
/* op_info op_info_128_170 [] */
op_table op_128_170 = {"op_128_170", 128, 170, op_info_128_170};
/* Table for fnt1 to fnt4 (opcodes 235 to 238) inclusive. */
op_info fnt_n [] =
{
{235, FONT1, 1, "1"},
{236, FONT2, 1, "2"},
{237, FONT3, 1, "3"},
{238, FONT4, 1, "-4"}
};
/* op_info fnt_n [] */
op_table fnt = {FONT, 235, 238, fnt_n};
/* Function prototypes */
Void mem_viol __((int sig));
Void give_help (VOID);
int parse __((char * s));
Void process __((char * s));
int open_dtl __((char * dtl_file, FILE ** pdtl));
int open_dvi __((char * dvi_file, FILE ** pdvi));
int dt2dv __((FILE * dtl, FILE * dvi));
Void * gmalloc __((long int size));
int cons_cmds __((int nprefixes, CmdPrefix * prefix, CmdTable cmds));
size_t getline __((FILE * fp, char * line, int max));
int read_line_char __((FILE * fp, int * c));
int read_char __((FILE * fp, int * ch));
COUNT read_variety __((FILE * dtl));
COUNT read_token __((FILE * dtl, char * token));
COUNT skip_space __((FILE * fp, int * ch));
COUNT read_misc __((FILE * fp, Token token));
COUNT read_mes __((FILE * fp, char * token));
int unread_char (VOID);
int find_command __((char * command, int * opcode));
int xferargs __((FILE * dtl, FILE * dvi, int opcode));
int setseq __((FILE * dtl, FILE * dvi));
int check_byte __((int byte));
int putbyte __((FILE * dvi, int onebyte));
U4 xferhex __((int n, FILE * dtl, FILE * dvi));
U4 xferoct __((int n, FILE * dtl, FILE * dvi));
U4 xferunsigned __((int n, FILE * dtl, FILE * dvi));
S4 xfersigned __((int n, FILE * dtl, FILE * dvi));
U4 xferstring __((FILE * dtl, FILE * dvi));
U4 xferlenstring __((int n, FILE * dtl, FILE * dvi));
int save_dvi_loc __((int ln));
int restore_dvi_loc __((int ln));
int check_bmes __((FILE * dtl));
int check_emes __((FILE * dtl));
U4 getunsigned __((FILE * dtl));
S4 getsigned __((FILE * dtl));
int putunsigned __((int n, U4 unum, FILE * dvi));
int putsigned __((int n, S4 snum, FILE * dvi));
S4 xfer_bop_address __((FILE * dtl, FILE * dvi));
S4 xfer_postamble_address __((FILE * dtl, FILE * dvi));
int puttable __((op_table table, int opcode, FILE * dtl, FILE * dvi));
U4 special __((FILE * dtl, FILE * dvi, int n));
int fontdef __((FILE * dtl, FILE * dvi, int n));
U4 preamble __((FILE * dtl, FILE * dvi));
int postamble __((FILE * dtl, FILE * dvi));
int post_post __((FILE * dtl, FILE * dvi));
Void dinfo (VOID);
Void dexit __((int n));
/* check whether compiler is standard C */
/* at my site, gcc 2.2.2 on Sun/OS uses a BSD library, not an ANSI library */
#ifdef __STDC__
# if __STDC__ - 1 /* __STDC__ defined, but != 1 => substandard C */
# define STD_C (-1)
# else /* standard C, except for BSD library */
# define STD_C 1
# endif
#else /* nonstandard C */
# define STD_C 0
#endif /* __STDC__ */
typedef struct
{
char * keyword; /* command line option keyword */
int * p_var; /* pointer to option variable */
char * desc; /* description of keyword and value */
} Options;
Options opts[] =
{
{"-debug", &debug, "detailed debugging"},
{"-group", &group, "each DTL command is in parentheses"},
{NULL, NULL, NULL}
};
/* opts[] */
COUNT dtl_line_num = 0; /* number of DTL file lines read */
#define NLOCS 2
long int dvi_loc[NLOCS] = {0L, 0L}; /* fseek offset in DVI file : for strings */
char * progname = ""; /* intended for name of this program */
int nfile = 0; /* number of filename arguments on the command line */
#define PRINT_PROGNAME fprintf (stderr, "%s ", progname)
FILE * dtl = stdin;
FILE * dvi = stdout; /* ! Perilous to monitors! */
int
main
#ifdef __STDC__
(int argc, char * argv[])
#else
(argc, argv)
int argc;
char * argv[];
#endif
{
Void (*handler)(int); /* Previous signal handler */
progname = argv[0]; /* name of this program */
/* memory violation signal handler */
handler = signal (SIGSEGV, mem_viol);
/* message about compiler */
/* NB: Our Sun/OS library is BSD, even though gcc 2.2.2 is ANSI */
fprintf (stderr,
"program \"%s\" version %s compiled %s %s in %sstandard C.\n",
progname, VERSION, __DATE__, __TIME__,
(STD_C == 1 ? "" : (STD_C < 0 ? "sub-" : "non-")));
/* interpret command line arguments */
if (argc < 3) /* less than two command line arguments, so give help */
give_help();
else
{
int i;
for (i=1; i < argc; i++)
parse (argv[i]);
if (nfile < 2) /* less than two filename arguments, so give help */
give_help();
else
/* the real works */
dt2dv (dtl, dvi);
}
return 0; /* OK */
}
/* end main */
Void
mem_viol
#ifdef __STDC__
(int sig)
#else
(sig)
int sig;
#endif
{
Void (* handler) (int);
handler = signal (SIGSEGV, mem_viol);
if (sig != SIGSEGV)
{
PRINT_PROGNAME;
fprintf (stderr,
"(mem_viol) : called with wrong signal!\n");
}
PRINT_PROGNAME;
fprintf (stderr, "(mem_viol) : RUNTIME MEMORY ERROR : memory violation, ");
fprintf (stderr, "dtl line >= ");
fprintf (stderr, WF, dtl_line_num);
fprintf (stderr, "\n");
dexit (1);
}
/* mem_viol */
Void
give_help (VOID)
{
int i;
char * keyword;
fprintf (stderr, "usage: ");
PRINT_PROGNAME;
fprintf (stderr, "dtl_file dvi_file");
fprintf (stderr, "\n");
for (i=0; (keyword = opts[i].keyword) != NULL; i++)
{
fprintf (stderr, " ");
fprintf (stderr, "[%s]", keyword);
fprintf (stderr, " ");
fprintf (stderr, "%s", opts[i].desc);
fprintf (stderr, "\n");
}
fprintf (stderr, "If dtl_file is \"-\", stdin is read.\n");
fprintf (stderr, "If dvi_file is \"-\", stdout is written.\n");
fprintf (stderr, "Messages, like this one, go to stderr.\n");
}
/* give_help */
int
parse
#ifdef __STDC__
(char * s)
#else
(s)
char * s;
#endif
{
int i;
char * keyword;
for (i=0; (keyword = opts[i].keyword) != NULL; i++)
{
if (strncmp (s, keyword, strlen (keyword)) == 0)
{
*(opts[i].p_var) = 1; /* turn option on */
return i;
}
}
/* not an option, so assume it's a filename */
process (s);
return i;
}
/* parse */
Void
process
#ifdef __STDC__
(char * s)
#else
(s)
char * s;
#endif
{
extern FILE * dtl, * dvi;
extern int nfile;
if (nfile == 0) /* first filename assumed to be DTL input */
{
if (strcmp (s, "-") == 0)
dtl = stdin;
else
open_dtl (s, &dtl);
}
else if (nfile == 1) /* second filename assumed to be DVI output */
{
if (strcmp (s, "-") == 0)
dvi = stdout;
else
open_dvi (s, &dvi);
}
else
{
PRINT_PROGNAME;
fprintf (stderr,
"(process) : at most two filenames allowed.\n");
exit (1);
}
++ nfile;
}
/* process */
int
open_dtl
#ifdef __STDC__
(char * dtl_file, FILE ** pdtl)
#else
(dtl_file, pdtl)
char * dtl_file;
FILE ** pdtl;
#endif
/* I: dtl_file; I: pdtl; O: *pdtl. */
{
if (pdtl == NULL)
{
PRINT_PROGNAME;
fprintf (stderr,
"(open_dtl) : INTERNAL ERROR : address of dtl variable is NULL.\n");
dexit (1);
}
*pdtl = fopen (dtl_file, "r");
if (*pdtl == NULL)
{
PRINT_PROGNAME;
fprintf (stderr,
"(open_dtl) : DTL FILE ERROR : Cannot open \"%s\" for text reading.\n",
dtl_file);
dexit (1);
}
return 1; /* OK */
}
/* open_dtl */
int
open_dvi
#ifdef __STDC__
(char * dvi_file, FILE ** pdvi)
#else
(dvi_file, pdvi)
char * dvi_file;
FILE ** pdvi;
#endif
/* I: dvi_file; I: pdvi; O: *pdvi. */
{
if (pdvi == NULL)
{
PRINT_PROGNAME;
fprintf (stderr,
"(open_dvi) : INTERNAL ERROR : address of dvi variable is NULL.\n");
dexit (1);
}
*pdvi = fopen (dvi_file, "wb");
if (*pdvi == NULL)
{
PRINT_PROGNAME;
fprintf (stderr,
"(open_dvi) : DVI FILE ERROR : Cannot open \"%s\" for binary writing.\n",
dvi_file);
dexit (1);
}
return 1; /* OK */
}
/* open_dvi */
COUNT dtl_read = 0; /* bytes read from dtl file */
COUNT dvi_written = 0; /* bytes written to dvi file */
word_t last_bop_address = -1; /* byte address of last bop; first bop uses -1 */
word_t postamble_address = -1; /* byte address of postamble */
COUNT ncom = 0; /* commands successfully read and interpreted from dtl file */
COUNT com_read = 0; /* bytes read in current (command and arguments), */
/* since and including the opening BCOM_CHAR, if any */
int
dt2dv
#ifdef __STDC__
(FILE * dtl, FILE * dvi)
#else
(dtl, dvi)
FILE * dtl;
FILE * dvi;
#endif
{
int nprefixes = 0; /* number of prefixes in cmd_prefixes[] list. */
Token dtl_cmd = ""; /* DTL command name */
COUNT nread = 0; /* number of bytes read by a function from dtl file. */
nprefixes = sizeof (cmd_prefixes) / sizeof (CmdPrefix);
/* Construct array of all 256 DTL commands */
(Void) cons_cmds (nprefixes, cmd_prefixes, cmd_table);
/* DTL commands have the form "[ ]*command arg ... arg[ ]*", */
/* possibly enclosed in a BCOM, ECOM pair, */
/* and are separated by optional whitespace, typically newlines. */
/* That is, each command and its arguments are parenthesised, */
/* with optional spaces after the BCOM and before the ECOM, if any. */
/* dt2dv is now at the very start of the DTL file */
dtl_line_num = 0;
dtl_read = 0;
/* The very first thing should be the "variety" signature */
nread = read_variety (dtl);
/* while not end of dtl file or reading error, */
/* read, interpret, and write commands */
while (!feof (dtl))
{
int opcode;
com_read = 0;
if (group)
{
/* BCOM check */
Token token = ""; /* DTL token */
nread = read_token (dtl, token);
/* test for end of input, or reading error */
if (strlen (token) == 0)
{
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(dt2dv) : end of input, or reading error.\n");
}
break;
}
/* test whether this command begins correctly */
else if (strcmp (token, BCOM) != 0)
{
PRINT_PROGNAME;
fprintf (stderr, "(dt2dv) : DTL FILE ERROR : ");
fprintf (stderr, "command must begin with \"%s\", ", BCOM);
fprintf (stderr, "not '%c' (%d).\n", token[0], token[0]);
dexit (1);
}
/* end BCOM check */
}
/* read the command name */
nread = read_token (dtl, dtl_cmd);
/* test for end of input, or reading error */
if (strlen (dtl_cmd) == 0)
{
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr,
"(dt2dv) : end of input, or reading error.\n");
}
break;
}
else
{
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(dt2dv) : command ");
fprintf (stderr, WF, ncom);
fprintf (stderr, " = \"%s\".\n", dtl_cmd);
}
/* find opcode for this command */
if (find_command (dtl_cmd, &opcode) == 1)
{
/* write the opcode, if we can */
putbyte (dvi, opcode);
/* treat the arguments, if any */
xferargs (dtl, dvi, opcode);
}
else if (dtl_cmd[0] == BSEQ_CHAR)
{
/* sequence of font characters for SETCHAR */
setseq (dtl, dvi);
}
else
{
PRINT_PROGNAME;
fprintf (stderr,
"(dt2dv) : DTL FILE ERROR : unknown command \"%s\".\n",
dtl_cmd);
dexit (1);
}
}
if (group)
{
/* seek ECOM after command's last argument and optional whitespace */
Token token = ""; /* DTL token */
nread = read_token (dtl, token);
/* test for end of input, or reading error */
if (strlen (token) == 0)
{
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr,
"(dt2dv) : end of input, or reading error.\n");
}
break;
}
if (strcmp (token, ECOM) != 0)
{
PRINT_PROGNAME;
fprintf (stderr, "(dt2dv) : DTL FILE ERROR : ");
fprintf (stderr, "\"%s\" expected, not '%c' (%d).\n",
ECOM, token[0], token[0]);
dexit (1);
}
/* end ECOM check */
}
++ ncom; /* one more command successfully read and interpreted */
}
/* end while */
PRINT_PROGNAME;
fprintf (stderr, "(dt2dv) : Read ");
fprintf (stderr, WF, dtl_read);
fprintf (stderr, " DTL bytes, wrote ");
fprintf (stderr, WF, dvi_written);
fprintf (stderr, " DVI bytes.\n");
fprintf (stderr, "Completely interpreted ");
fprintf (stderr, WF, ncom);
fprintf (stderr, " DVI command%s.\n", (ncom == 1 ? "" : "s"));
return 1; /* OK */
}
/* dt2dv */
Void *
gmalloc
#ifdef __STDC__
(long int size)
#else
(size)
long int size;
#endif
{
Void * p = NULL;
if (size < 1)
{
PRINT_PROGNAME;
fprintf (stderr, "(gmalloc) : INTERNAL ERROR : ");
fprintf (stderr,
"unreasonable request to malloc %ld bytes\n",
size);
dexit (1);
}
p = malloc ((size_t) size);
if (p == NULL)
{
PRINT_PROGNAME;
fprintf (stderr, "(gmalloc) : MEMORY ALLOCATION ERROR : ");
fprintf (stderr,
"operating system failed to malloc %ld bytes\n",
size);
dexit (1);
}
return (p);
}
/* gmalloc */
int
cons_cmds
#ifdef __STDC__
(int nprefixes, CmdPrefix * prefix, CmdTable cmds)
#else
(nprefixes, prefix, cmds)
int nprefixes;
CmdPrefix * prefix;
CmdTable cmds;
#endif
{
int code; /* first opcode for a given command prefix */
int opcode; /* command's opcode */
int nsuffixes; /* number of commands with a given prefix */
int isuffix; /**** integer suffix, of at most three digits ****/
String suffix; /* suffix string generated from integer suffix */
size_t plen = 0; /* prefix length */
size_t slen; /* suffix length */
size_t clen; /* whole command name length */
int i, j; /* loop indices */
for (i=0; i < nprefixes; prefix++, i++)
{
code = prefix->first_code;
if (code < 0 || code > 255)
{
PRINT_PROGNAME;
fprintf (stderr, "(cons_cmds) : INTERNAL ERROR : ");
fprintf (stderr,
"prefix listed internally with code = %d, must be 0 to 255\n",
code);
dexit (1);
}
if (prefix->has_suffix)
{
plen = strlen (prefix->name);
/**** Suffixes in DTL are Integers, in Sequence */
if (prefix->last_suffix < prefix->first_suffix)
{
PRINT_PROGNAME;
fprintf (stderr, "(cons_cmds) : INTERNAL ERROR : ");
fprintf (stderr,
"prefix's last suffix %d < first suffix (%d)\n",
prefix->last_suffix, prefix->first_suffix);
dexit (1);
}
nsuffixes = prefix->last_suffix - prefix->first_suffix + 1;
opcode = prefix->first_code;
for (j=0; j < nsuffixes; j++, opcode++)
{
isuffix = prefix->first_suffix + j;
if (0 <= code && code <= 127) /* SETCHAR */
{
/* SETCHAR's suffix is written in uppercase hexadecimal */
sprintf (suffix, "%02X", isuffix);
}
else /* 128 <= code && code <= 255 */ /* other DTL commands */
{
/* other commands' suffices are written in decimal */
sprintf (suffix, "%d", isuffix);
}
slen = strlen (suffix);
clen = plen + slen;
cmds[opcode] = gmalloc (clen+1);
strcpy (cmds[opcode], prefix->name);
strcat (cmds[opcode], suffix);
}
}
else /* command name = prefix */
{
clen = plen;
opcode = prefix->first_code;
cmds[opcode] = gmalloc (clen+1);
strcpy (cmds[opcode], prefix->name);
}
}
return 1; /* OK */
}
/* cons_cmds */
COUNT
read_variety
#ifdef __STDC__
(FILE * dtl)
#else
(dtl)
FILE * dtl;
#endif
/* read and check DTL variety signature */
/* return number of DTL bytes written */
/* DTL variety is _NEVER_ grouped by BCOM and ECOM. */
/* Uniformity here enables the program easily to modify its behavior. */
{
COUNT vread = 0; /* number of DTL bytes read by read_variety */
COUNT nread = 0; /* number of DTL bytes read by read_token */
Token token = "";
/* read the DTL VARIETY keyword */
nread =
read_token (dtl, token);
vread += nread;
/* test whether signature begins correctly */
if (strcmp (token, "variety") != 0)
{
PRINT_PROGNAME;
fprintf (stderr, "(read_variety) : DTL FILE ERROR : ");
fprintf (stderr, "DTL signature must begin with \"%s\", not \"%s\".\n",
"variety", token);
dexit (1);
}
/* read the DTL variety */
nread =
read_token (dtl, token);
vread += nread;
/* test whether variety is correct */
if (strcmp (token, VARIETY) != 0)
{
PRINT_PROGNAME;
fprintf (stderr, "(read_variety) : DTL FILE ERROR : ");
fprintf (stderr, "DTL variety must be \"%s\", not \"%s\".\n",
VARIETY, token);
dexit (1);
}
PRINT_PROGNAME;
fprintf (stderr, "(read_variety) : DTL variety %s is OK.\n", VARIETY);
return vread; /* OK */
}
/* read_variety */
COUNT
read_token
#ifdef __STDC__
(FILE * dtl, char * token)
#else
(dtl, token)
FILE * dtl;
char * token;
#endif
/* read next token from dtl file. */
/* return number of DTL bytes read. */
/* A token is:
a string from BMES_CHAR to the next unescaped EMES_CHAR, inclusive;
BCOM or ECOM, unless these are empty strings;
BSEQ or ESEQ;
any other sequence of non-whitespace characters.
*/
{
COUNT nread; /* number of DTL bytes read by read_token */
int ch; /* most recent character read */
nread = 0;
/* obtain first non-space character */
/* add to nread the number of characters read from dtl by skip_space */
nread +=
skip_space (dtl, &ch);
if (ch < 0)
{
/* end of dtl file */
/* write an empty token */
strcpy (token, "");
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(read_token) : end of dtl file.\n");
}
}
else if (group && ch == BCOM_CHAR)
{
strcpy (token, BCOM);
}
else if (group && ch == ECOM_CHAR)
{
strcpy (token, ECOM);
}
else
{
token[0] = ch;
token[1] = '\0';
if (ch == BMES_CHAR) /* string token; read until unescaped EMES_CHAR */
{
nread +=
read_mes (dtl, token+1);
}
else if (ch == BSEQ_CHAR || ch == ESEQ_CHAR)
{
/* token is complete */
}
else /* any other string not containing (ECOM_CHAR or) whitespace */
{
nread +=
read_misc (dtl, token+1);
}
}
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr,
"(read_token) : token = \"%s\"\n",
token);
}
return (nread); /* number of bytes read from dtl file */
}
/* read_token */
size_t
getline
#ifdef __STDC__
(FILE * fp, char * line, int max)
#else
(fp, line, max)
FILE * fp;
char * line;
int max;
#endif
/* read a line from fp, return length */
/* adapted from K&R (second, alias ANSI C, edition, 1988), page 165 */
{
if (fgets (line, max, fp) == NULL)
return 0;
else
return strlen (line);
}
/* getline */
int
read_line_char
#ifdef __STDC__
(FILE * fp, int * c)
#else
(fp, c)
FILE * fp;
int * c;
#endif
/* read one character from dtl_line if possible, */
/* otherwise read another dtl_line from fp */
/* return 1 if a character is read, 0 if at end of fp file */
{
extern Line dtl_line;
if (dtl_line.len == 0 || dtl_line.next >= dtl_line.len)
{
/* refill line buffer */
dtl_line.len = getline (fp, dtl_line.buf, MAXLINE);
dtl_line.next = 0;
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(read_line_char) : new DTL input line:\n");
fprintf (stderr, "\"%s\"", dtl_line.buf);
fprintf (stderr, "\n");
}
if (dtl_line.len == 0)
{
/* at end of DTL file */
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(read_line_char) : end of DTL file\n");
dinfo();
}
return 0;
}
}
*c = dtl_line.buf [dtl_line.next ++];
++ dtl_read;
++ com_read; /* count another DTL command character */
return 1;
}
/* read_line_char */
int
read_char
#ifdef __STDC__
(FILE * fp, int * ch)
#else
(fp, ch)
FILE * fp;
int * ch;
#endif
/* Read next character, if any, from file fp. */
/* Write it into *ch. */
/* If no character is read, then *ch value < 0. */
/* Return 1 if OK, 0 if EOF or error. */
{
int status = 1;
int c; /* in case ch points awry, we still have something in c. */
if (read_line_char (fp, &c) == 0)
{
/* end of fp file, or error reading it */
status = 0;
}
else
{
if (c > 255)
{
PRINT_PROGNAME;
fprintf (stderr,
"(read_char) : character %d not in range 0 to 255\n",
c);
dinfo();
status = 0;
}
else if ( ! isprint (c) && ! isspace (c))
{
PRINT_PROGNAME;
fprintf (stderr,
"(read_char) : character %d %s.\n",
c,
"not printable and not white space");
dinfo();
status = 0;
}
}
*ch = c;
return status;
}
/* read_char */
COUNT
skip_space
#ifdef __STDC__
(FILE * fp, int * ch)
#else
(fp, ch)
FILE * fp;
int * ch;
#endif
/* Skip whitespace characters in file fp. */
/* Write in *ch the last character read from fp, */
/* or < 0 if fp could not be read. */
/* Return number of characters read from fp. */
{
int c; /* character read (if any) */
COUNT count; /* number (0 or more) of whitespace characters read */
int nchar; /* number (0 or 1) of characters read by read_char */
/* loop ends at: end of fp file, or reading error, or not a white space */
for (count=0; ((nchar = read_char (fp, &c)) == 1 && isspace (c)); ++count)
{
/* otherwise, more white spaces to skip */
if (debug)
{
/* report when each DTL end of line is reached */
if (c == '\n')
{
PRINT_PROGNAME;
fprintf (stderr, "(skip_space) : ");
fprintf (stderr, "end of DTL line (at least) ");
fprintf (stderr, WF, dtl_line_num);
fprintf (stderr, "\n");
++ dtl_line_num;
}
}
}
if (nchar == 0)
{
c = -1;
}
*ch = c; /* c will be < 0 if read_char could not read fp */
return (count + nchar);
}
/* skip_space */
COUNT
read_misc
#ifdef __STDC__
(FILE * fp, Token token)
#else
(fp, token)
FILE * fp;
Token token;
#endif
{
int c;
int count;
/* loop ends at: end of fp file, or reading error, or a space */
for (count=0; count <= MAXTOKLEN; ++count)
{
if (read_char (fp, &c) == 0 || isspace (c))
break;
if (group && c == ECOM_CHAR)
{
(Void) unread_char ();
break;
}
token[count] = c;
}
token[count] = '\0';
return count;
}
/* read_misc */
COUNT
read_mes
#ifdef __STDC__
(FILE * fp, char * token)
#else
(fp, token)
FILE * fp;
char * token;
#endif
/* called **AFTER** a BMES_CHAR has been read */
/* read file fp for characters up to next unescaped EMES_CHAR */
/* this is called a "string token" */
/* write string, including EMES_CHAR, into token[] */
/* return number of characters read from fp */
{
COUNT dtl_count; /* number of DTL characters read by read_mes from fp */
int more; /* flag more == 0 to terminate loop */
int escape; /* flag escape == 1 if previous character was ESC_CHAR */
int ch; /* current DTL character */
escape = 0;
more = 1;
dtl_count = 0;
while (more)
{
if (read_char (fp, &ch) == 0)
{
/* end of fp file, or reading error */
more = 0;
}
else /* error checking passed */
{
++ dtl_count;
if (ch == EMES_CHAR && escape == 0) /* end of string */
{
/* include final EMES_CHAR */
* token ++ = ch;
more = 0;
}
else if (ch == ESC_CHAR && escape == 0)
{
/* next character is not end of string */
escape = 1;
}
else
{
/* store any other character, */
/* including escaped EMES_CHAR and ESC_CHAR*/
* token ++ = ch;
escape = 0;
}
}
}
* token = '\0';
return dtl_count;
}
/* read_mes */
int
unread_char (VOID)
/* wind input back, to allow rereading of one character */
/* return 1 if this works, 0 on error */
{
extern Line dtl_line;
int status;
if (dtl_line.next > 0)
{
-- dtl_line.next; /* back up one character in dtl_line */
-- dtl_read; /* correct the count of DTL characters */
-- com_read; /* count another DTL command character */
status = 1; /* OK */
}
else /* current DTL line is empty */
{
status = 0; /* error */
}
return status;
}
/* unread_char */
int
find_command
#ifdef __STDC__
(char * command, int * opcode)
#else
(command, opcode)
char * command;
int * opcode;
#endif
{
int found;
int i;
found = 0;
for (i=0; i < 256; i++)
{
if (strcmp (command, cmd_table[i]) == 0)
{
found = 1;
break;
}
}
*opcode = i;
return found;
}
/* find_command */
int
check_byte
#ifdef __STDC__
(int byte)
#else
(byte)
int byte;
#endif
{
if (byte < 0 || byte > 255)
{
PRINT_PROGNAME;
fprintf (stderr, "(check_byte) : INTERNAL ERROR : ");
fprintf (stderr, "byte %d not in the range of 0 to 255.\n", byte);
dexit (1);
}
return 1; /* OK */
}
/* check_byte */
int
xferargs
#ifdef __STDC__
(FILE * dtl, FILE * dvi, int opcode)
#else
(dtl, dvi, opcode)
FILE * dtl;
FILE * dvi;
int opcode;
#endif
{
int n;
if (opcode >= 0 && opcode <= 127)
; /* SETCHAR uses no data */
else if (opcode >= 128 && opcode <= 170)
{
word_t this_bop_address = last_bop_address;
if (opcode == 139) /* BOP */
{
this_bop_address = dvi_written - 1;
}
puttable (op_128_170, opcode, dtl, dvi);
if (opcode == 139) /* BOP */
{
xfer_bop_address (dtl, dvi);
last_bop_address = this_bop_address;
}
}
else if (opcode >= 171 && opcode <= 234)
; /* FONTNUM uses no data */
else if (opcode >= 235 && opcode <= 238)
puttable (fnt, opcode, dtl, dvi);
else if (opcode >= 239 && opcode <= 242)
{
n = opcode - 238;
special (dtl, dvi, n);
}
else if (opcode >= 243 && opcode <= 246)
{
n = opcode - 242;
fontdef (dtl, dvi, n);
}
else if (opcode == 247)
preamble (dtl, dvi);
else if (opcode == 248)
postamble (dtl, dvi);
else if (opcode == 249)
post_post (dtl, dvi);
else if (opcode >= 250 && opcode <= 255)
; /* these, undefined, opcodes use no data */
else
{
PRINT_PROGNAME;
fprintf (stderr,
"(xferargs) : opcode %d not handled.\n",
opcode);
}
return 1; /* OK */
}
/* xferargs */
int
setseq
#ifdef __STDC__
(FILE * dtl, FILE * dvi)
#else
(dtl, dvi)
FILE * dtl;
FILE * dvi;
#endif
/* Called _after_ a BSEQ_CHAR command */
/* Read bytes from dtl file, */
/* writing corresponding SETCHAR or SET1 commands to DVI file, */
/* _until_ unescaped ESEQ_CHAR is found */
/* Return 1 if OK, 0 on error */
/**** dt2dv assumes 8 bit characters, ****/
/**** but some day one might change that. ****/
{
int status = 1; /* status = 1 if OK, 0 if error */
int more; /* sequence of font characters continuing? */
int escape = 0; /* flag set if previous character was an escape */
int ch; /* character read from DTL file */
more = 1;
while (more)
{
/* ignore read_char status, to allow unprintable characters */
(Void) read_char (dtl, &ch);
/* but check for end of dtl file, or serious file reading error */
if (ch < 0)
{
PRINT_PROGNAME;
fprintf (stderr, "(setseq) : ");
fprintf (stderr, "end of dtl file, ");
fprintf (stderr, "or serious dtl file reading error\n");
dinfo();
more = 0;
status = 0; /* bad news */
}
else /* read dtl file, okay */
{
if (ch == ESC_CHAR && escape == 0) /* escape next character */
{
escape = 1;
}
else
{
if (ch == ESEQ_CHAR && escape == 0) /* end of sequence */
{
more = 0;
}
else if (ch <= 127) /* can use SETCHAR */
{
putbyte (dvi, ch);
}
else if (ch <= 255) /* can use SET1 */
{
putbyte (dvi, 128); /* SET1 opcode */
putunsigned (1, (U4) ch, dvi);
}
else
{
PRINT_PROGNAME;
fprintf (stderr, "(setseq) : ");
fprintf (stderr,
"ERROR : DTL character %d is not in range 0 to 255\n",
ch);
dexit (1);
more = 0;
status = 0; /* Error, because dt2dv assumes 8 bit characters */
}
escape = 0; /* current ch is not an escape character */
}
}
}
return status;
}
/* setseq */
int
putbyte
#ifdef __STDC__
(FILE * dvi, int byte)
#else
(dvi, byte)
FILE * dvi;
int byte;
#endif
{
check_byte (byte);
/* if (fprintf (dvi, "%c", byte) != 1) */
if (fprintf (dvi, "%c", byte) < 0)
{
PRINT_PROGNAME;
fprintf (stderr,
"(putbyte) : DVI FILE ERROR : cannot write to dvi file.\n");
dexit (1);
}
++ dvi_written;
return 1; /* OK */
}
/* putbyte */
U4
xferhex
#ifdef __STDC__
(int n, FILE * dtl, FILE * dvi)
#else
(n, dtl, dvi)
int n;
FILE * dtl;
FILE * dvi;
#endif
/* translate unsigned n-byte hexadecimal number from dtl to dvi file. */
/* return value of hexadecimal number */
{
U4 unum = 0; /* at most this space needed */
COUNT nread = 0; /* number of DTL bytes read by read_token */
int nconv = 0; /* number of arguments converted by sscanf */
Token token = ""; /* DTL token */
if (n < 1 || n > 4)
{
PRINT_PROGNAME;
fprintf (stderr,
"(xferhex) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
n);
dexit (1);
}
nread =
read_token (dtl, token);
nconv = sscanf (token, XF4, &unum);
if (nconv < 1)
{
PRINT_PROGNAME;
fprintf (stderr, "(xferhex) : DTL FILE ERROR : %s \"%s\".\n",
"hexadecimal number expected, not", token);
dexit (1);
}
putunsigned (n, unum, dvi);
return unum;
}
/* xferhex */
U4
xferoct
#ifdef __STDC__
(int n, FILE * dtl, FILE * dvi)
#else
(n, dtl, dvi)
int n;
FILE * dtl;
FILE * dvi;
#endif
/* translate unsigned n-byte octal number from dtl to dvi file. */
/* return value of octal number */
{
U4 unum = 0; /* at most this space needed */
COUNT nread = 0; /* number of DTL bytes read by read_token */
int nconv = 0; /* number of arguments converted by sscanf */
Token token = ""; /* DTL token */
if (n < 1 || n > 4)
{
PRINT_PROGNAME;
fprintf (stderr,
"(xferoct) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
n);
dexit (1);
}
nread =
read_token (dtl, token);
nconv = sscanf (token, OF4, &unum);
if (nconv < 1)
{
PRINT_PROGNAME;
fprintf (stderr, "(xferoct) : DTL FILE ERROR : %s \"%s\".\n",
"octal number expected, not", token);
dexit (1);
}
putunsigned (n, unum, dvi);
return unum;
}
/* xferoct */
U4
xferunsigned
#ifdef __STDC__
(int n, FILE * dtl, FILE * dvi)
#else
(n, dtl, dvi)
int n;
FILE * dtl;
FILE * dvi;
#endif
/* translate unsigned n-byte number from dtl to dvi file. */
/* return value of unsigned number */
{
U4 unum = 0; /* at most this space needed */
unum = getunsigned (dtl);
putunsigned (n, unum, dvi);
return unum;
}
/* xferunsigned */
S4
xfersigned
#ifdef __STDC__
(int n, FILE * dtl, FILE * dvi)
#else
(n, dtl, dvi)
int n;
FILE * dtl;
FILE * dvi;
#endif
/* translate signed n-byte number from dtl to dvi file. */
/* return value of signed number */
{
S4 snum = 0;
snum = getsigned (dtl);
putsigned (n, snum, dvi);
return snum;
}
/* xfersigned */
U4
getunsigned
#ifdef __STDC__
(FILE * dtl)
#else
(dtl)
FILE * dtl;
#endif
/* read unsigned number from dtl file. */
/* return value of unsigned number */
{
U4 unum = 0; /* at most this space needed */
COUNT nread = 0; /* number of DTL bytes read by read_token */
int nconv = 0; /* number of arguments converted by sscanf */
Token token = ""; /* DTL token */
nread =
read_token (dtl, token);
nconv = sscanf (token, UF4, &unum);
if (nconv < 1)
{
PRINT_PROGNAME;
fprintf (stderr, "(getunsigned) : DTL FILE ERROR : %s \"%s\".\n",
"unsigned number expected, not", token);
dexit (1);
}
return unum;
}
/* getunsigned */
S4
getsigned
#ifdef __STDC__
(FILE * dtl)
#else
(dtl)
FILE * dtl;
#endif
/* read signed number from dtl file. */
/* return value of signed number */
{
S4 snum = 0;
COUNT nread = 0; /* number of DTL bytes read by read_token */
int nconv = 0; /* number of sscanf arguments converted and assigned */
Token token = "";
nread =
read_token (dtl, token);
nconv = sscanf (token, SF4, &snum);
if (nconv < 1)
{
PRINT_PROGNAME;
fprintf (stderr, "(getsigned) : DTL FILE ERROR : %s \"%s\".\n",
"signed number expected, not", token);
dexit (1);
}
return snum;
}
/* getsigned */
int
putunsigned
#ifdef __STDC__
(int n, U4 unum, FILE * dvi)
#else
(n, unum, dvi)
int n;
U4 unum;
FILE * dvi;
#endif
/* put unsigned in-byte integer to dvi file */
/* DVI format uses Big-endian storage of numbers: */
/* most significant byte is first. */
/* return number of bytes written. */
{
Byte ubyte[4]; /* at most 4 bytes needed in DVI format */
int i;
if (n < 1 || n > 4)
{
PRINT_PROGNAME;
fprintf (stderr,
"(putunsigned) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
n);
dexit (1);
}
/* Big-endian storage. */
for (i = 0; i < n; i++)
{
ubyte[i] = (Byte) (unum % 256);
unum /= 256;
}
/* Reverse order for big-endian representation. */
for (i = n-1; i >= 0; i--)
{
putbyte (dvi, (int) ubyte[i]);
}
return n;
}
/* putunsigned */
int
putsigned
#ifdef __STDC__
(int n, S4 snum, FILE * dvi)
#else
(n, snum, dvi)
int n;
S4 snum;
FILE * dvi;
#endif
/* put signed in-byte integer to dvi file */
/* DVI format uses 2's complement Big-endian storage of signed numbers: */
/* most significant byte is first. */
/* return number of bytes written. */
{
/* Will this deal properly with the sign? */
if (n < 1 || n > 4)
{
PRINT_PROGNAME;
fprintf (stderr,
"(putsigned) : INTERNAL ERROR : asked for %d bytes. Must be 1 to 4.\n",
n);
dexit (1);
}
/* How do we ensure 2's complement representation? */
/* Here's a trick that I hope is portable, given ANSI C. */
/* See K&R (2nd edition), Appendix A6.2 "Integral Conversions". */
/* Convert snum to U4 data type */
putunsigned (n, (U4) snum, dvi);
return n;
}
/* putsigned */
U4
xferstring
#ifdef __STDC__
(FILE * dtl, FILE * dvi)
#else
(dtl, dvi)
FILE * dtl;
FILE * dvi;
#endif
/* transfer a string from dtl to dvi file, */
/* return number of bytes written to dvi file. */
{
U4 n;
check_bmes (dtl);
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr,
"(xferstring) : string is: \"");
}
for (n=0; ; n++)
{
int ch;
if (read_char (dtl, &ch) == 0)
{
/* end of dtl file, or reading error */
fprintf (stderr, "\n");
PRINT_PROGNAME;
fprintf (stderr, "(xferstring) : DTL FILE ERROR : cannot read string[");
fprintf (stderr, UF4, n);
fprintf (stderr, "] from dtl file.\n");
dexit (1);
}
if (debug)
{
fprintf (stderr, "%c", ch);
}
if (ch == EMES_CHAR)
{
(Void) unread_char ();
break;
}
else
{
putbyte (dvi, ch);
}
}
/* end for */
if (debug)
{
fprintf (stderr, "\".\n");
}
check_emes (dtl);
return n;
}
/* xferstring */
U4
xferlenstring
#ifdef __STDC__
(int n, FILE * dtl, FILE * dvi)
#else
(n, dtl, dvi)
int n;
FILE * dtl;
FILE * dvi;
#endif
/* transfer (length and) quoted string from dtl to dvi file, */
/* return number of bytes written to dvi file. */
{
U4 k, k2;
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(xferlenstring) : about to transfer string.\n");
}
save_dvi_loc (0);
/* k[n] : length of special string */
/* If DTL file has been edited, then this length may be wrongly recorded, */
/* but later we'll come back to here in the DVI file and fix it */
k = xferunsigned (n, dtl, dvi);
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(xferlenstring) : string's nominal length k = ");
fprintf (stderr, UF4, k);
fprintf (stderr, " characters.\n");
}
/* x[k] : special string */
k2 = xferstring (dtl, dvi);
save_dvi_loc (1);
if (k2 != k)
{
PRINT_PROGNAME;
fprintf (stderr, "(special) : WARNING : string length (");
fprintf (stderr, UF4, k);
fprintf (stderr, ") in DTL file is wrong\n");
fprintf (stderr, "Writing correct value (");
fprintf (stderr, UF4, k2);
fprintf (stderr, ") to DVI file\n");
restore_dvi_loc (0);
-- dvi_written;
putunsigned (n, k2, dvi);
restore_dvi_loc (1);
}
return (n + k2);
}
/* xferlenstring */
int save_dvi_loc
#ifdef __STDC__
(int ln)
#else
(ln)
int ln;
#endif
{
if (ln < 0 || ln >= NLOCS)
{
PRINT_PROGNAME;
fprintf (stderr,
"(save_dvi_loc) : INTERNAL ERROR : bad loc number %d, ", ln);
fprintf (stderr, "must be between 0 and %d\n", NLOCS-1);
dexit (1);
}
dvi_loc[ln] = ftell (dvi);
if (dvi_loc[ln] == -1L)
{
PRINT_PROGNAME;
fprintf (stderr, "(save_dvi_loc) : DVI FILE ERROR : error on ftell");
fprintf (stderr, "\n");
dexit (1);
}
return 0; /* success */
}
/* save_dvi_loc */
int restore_dvi_loc
#ifdef __STDC__
(int ln)
#else
(ln)
int ln;
#endif
{
if (ln < 0 || ln >= NLOCS)
{
PRINT_PROGNAME;
fprintf (stderr,
"(restore_dvi_loc) : INTERNAL ERROR : bad loc number %d, ", ln);
fprintf (stderr, "must be between 0 and %d\n", NLOCS-1);
dexit (1);
}
if (fseek (dvi, dvi_loc[ln], FILE_BEGIN) != 0)
{
PRINT_PROGNAME;
fprintf (stderr, "(restore_dvi_loc) : DVI FILE ERROR : error on fseek");
fprintf (stderr, " when DVI offset = %ld", dvi_loc[ln]);
fprintf (stderr, "\n");
dexit (1);
}
return 0; /* success */
}
/* restore_dvi_loc */
S4
xfer_bop_address
#ifdef __STDC__
(FILE * dtl, FILE * dvi)
#else
(dtl, dvi)
FILE * dtl;
FILE * dvi;
#endif
/* translate signed 4-byte bop address from dtl to dvi file. */
/* return value of bop address written to DVI file */
{
S4 snum = 0; /* at most this space needed for byte address */
COUNT nread = 0; /* number of DTL bytes read by read_token */
int nconv = 0; /* number of arguments converted by sscanf */
Token token = ""; /* DTL token */
nread +=
read_token (dtl, token);
nconv = sscanf (token, SF4, &snum);
if (nconv != 1)
{
PRINT_PROGNAME;
fprintf (stderr, "(xfer_bop_address) : DTL FILE ERROR : %s \"%s\".\n",
"signed number expected, not", token);
dexit (1);
}
if (snum != last_bop_address)
{
PRINT_PROGNAME;
fprintf (stderr, "(xfer_bop_address) : WARNING : byte address (");
fprintf (stderr, WF, snum);
fprintf (stderr, ")\n");
fprintf (stderr, "for previous bop in DTL file is wrong\n");
fprintf (stderr, "Writing correct value (");
fprintf (stderr, WF, last_bop_address);
fprintf (stderr, ") to DVI file\n");
}
putsigned (4, last_bop_address, dvi);
return last_bop_address;
}
/* xfer_bop_address */
S4
xfer_postamble_address
#ifdef __STDC__
(FILE * dtl, FILE * dvi)
#else
(dtl, dvi)
FILE * dtl;
FILE * dvi;
#endif
/* translate signed 4-byte postamble address from dtl to dvi file. */
/* return value of postamble address written to DVI file */
{
S4 snum = 0; /* at most this space needed for byte address */
COUNT nread = 0; /* number of DTL bytes read by read_token */
int nconv = 0; /* number of arguments converted by sscanf */
Token token = ""; /* DTL token */
nread +=
read_token (dtl, token);
nconv = sscanf (token, SF4, &snum);
if (nconv != 1)
{
PRINT_PROGNAME;
fprintf (stderr, "(xfer_postamble_address) : DTL FILE ERROR : ");
fprintf (stderr, "signed number expected, not \"%s\".\n", token);
dexit (1);
}
if (snum != postamble_address)
{
PRINT_PROGNAME;
fprintf (stderr, "(xfer_postamble_address) : WARNING : byte address (");
fprintf (stderr, WF, snum);
fprintf (stderr, ")\n");
fprintf (stderr, "for postamble in DTL file is wrong\n");
fprintf (stderr, "Writing correct value (");
fprintf (stderr, WF, postamble_address);
fprintf (stderr, ") to DVI file\n");
}
putsigned (4, postamble_address, dvi);
return postamble_address;
}
/* xfer_postamble_address */
int
puttable
#ifdef __STDC__
(op_table table, int opcode, FILE * dtl, FILE * dvi)
#else
(table, opcode, dtl, dvi)
op_table table;
int opcode;
FILE * dtl;
FILE * dvi;
#endif
{
/* table: {char * name; int first, last; op_info * list; }; */
/* op_info: {int code; char * name; int nargs; char * args; }; */
op_info op; /* entry in table */
int i;
int pos; /* current position in string being scanned */
String args = "";
/* Defensive programming. */
if (opcode < table.first || opcode > table.last)
{
PRINT_PROGNAME;
fprintf (stderr,
"(puttable) : DTL FILE (OR INTERNAL) ERROR : opcode %d ", opcode);
fprintf (stderr, "is outside table %s [ %d to %d ] !\n",
table.name, table.first, table.last);
dexit (1);
}
op = table.list [ opcode - table.first ];
/* More defensive programming. */
if (opcode != op.code)
{
PRINT_PROGNAME;
fprintf (stderr,
"(puttable) : INTERNAL ERROR : opcode %d for command \"%s\" %s \"%s\".\n",
opcode, op.name, "faulty in table", table.name);
dexit (1);
}
/* process all the arguments, according to size and sign */
strncpy (args, op.args, MAXSTRLEN);
pos = 0;
for (i=0; i < op.nargs; i++)
{
int argtype = 0;
int nscan = 0; /* number of bytes read by sscanf */
int nconv = 0; /* number of sscanf arguments converted & assigned */
/* sscanf() does NOT advance over its input: */
/* C strings lack internal state information, which C files have. */
/* On Sun/OS, sscanf calls ungetc on the string it reads, */
/* which therefore has to be writable. */
nconv = sscanf (args + pos, "%d%n", &argtype, &nscan);
if (nconv < 1 || nscan < 1)
{
PRINT_PROGNAME;
fprintf (stderr,
"(puttable) : INTERNAL ERROR : internal read of table %s failed!\n",
table.name);
dexit (1);
}
pos += nscan;
if (argtype < 0)
xfersigned (-argtype, dtl, dvi);
else
xferunsigned (argtype, dtl, dvi);
}
/* end for */
return 1; /* OK */
}
/* puttable */
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
U4
special
#ifdef __STDC__
(FILE * dtl, FILE * dvi, int n)
#else
(dtl, dvi, n)
FILE * dtl;
FILE * dvi;
int n;
#endif
/* read special (1 <= n <= 4 byte) data from dtl, and write in dvi */
/* return number of bytes written */
{
U4 nk;
if (n < 1 || n > 4)
{
PRINT_PROGNAME;
fprintf (stderr, "(special) : DTL FILE ERROR : special %d, ", n);
fprintf (stderr, "range is 1 to 4.\n");
dexit (1);
}
/* k[n] : length of special string */
/* x[k] : special string */
/* nk = n + k */
nk = xferlenstring (n, dtl, dvi);
return (nk);
}
/* special */
int
check_bmes
#ifdef __STDC__
(FILE * dtl)
#else
(dtl)
FILE * dtl;
#endif
/* check that a BMES_CHAR is the next non-whitespace character in dtl */
{
int ch; /* next non-whitespace character in dtl */
/* ignore number of spaces skipped */
(Void) skip_space (dtl, &ch);
if (ch < 0)
{
PRINT_PROGNAME;
fprintf (stderr,
"(check_bmes) : DTL FILE ERROR : end of dtl file, or reading error\n");
dexit (1);
}
if (ch != BMES_CHAR)
{
PRINT_PROGNAME;
fprintf (stderr,
"(check_bmes) : DTL FILE ERROR : '%c' %s, not '%c' (%d).\n",
BMES_CHAR, "expected to precede string", ch, ch);
dexit (1);
}
return 1; /* OK */
}
/* check_bmes */
int
check_emes
#ifdef __STDC__
(FILE * dtl)
#else
(dtl)
FILE * dtl;
#endif
/* check that an EMES_CHAR is the next character in dtl */
{
int ch; /* dtl character */
if (read_char (dtl, &ch) == 0)
{
PRINT_PROGNAME;
fprintf (stderr,
"(check_emes) : DTL FILE ERROR : end of dtl file, or reading error\n");
dexit (1);
}
if (ch != EMES_CHAR)
{
PRINT_PROGNAME;
fprintf (stderr,
"(check_emes) : DTL FILE ERROR : '%c' %s, not '%c' (%d).\n",
EMES_CHAR, "expected to follow string", ch, ch);
dexit (1);
}
return 1; /* OK */
}
/* check_emes */
int
fontdef
#ifdef __STDC__
(FILE * dtl, FILE * dvi, int s)
#else
(dtl, dvi, s)
FILE * dtl;
FILE * dvi;
int s;
#endif
/* read fontdef fnt_def1 .. fnt_def4 from dtl, and write in dvi */
/* s is the fontdef suffix : 1 to 4 */
/* return number of bytes written */
{
U4 a, l, al;
U4 k;
if (s < 1 || s > 4)
{
PRINT_PROGNAME;
fprintf (stderr,
"(fontdef) : DTL FILE ERROR : font def %d, but range is 1 to 4.\n", s);
dexit (1);
}
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(fontdef) : about to read font number.\n");
}
/* k[s] : font number */
if (s == 4)
k = xfersigned (s, dtl, dvi);
else
k = xferunsigned (s, dtl, dvi);
if (debug)
{
PRINT_PROGNAME;
fprintf (stderr, "(fontdef) : font ");
fprintf (stderr, UF4, k);
fprintf (stderr, ".\n");
}
#ifdef HEX_CHECKSUM
/* c[4] : (hexadecimal) checksum : I (gt) would prefer this */
xferhex (4, dtl, dvi);
#else
/* c[4] : checksum (octal, for quick comparison with tftopl's .pl file) */
xferoct (4, dtl, dvi);
#endif
/* s[4] */
xferunsigned (4, dtl, dvi);
/* d[4] */
xferunsigned (4, dtl, dvi);
/* a[1] : length of font `area' (directory) portion of pathname string */
a = xferunsigned (1, dtl, dvi);
/* l[1] : length of font filename portion of pathname string */
l = xferunsigned (1, dtl, dvi);
/* n[a+l] : font pathname string */
/* al = a+l */
al = xferstring (dtl, dvi);
if (al != a + l)
{
PRINT_PROGNAME;
fprintf (stderr,
"(fontdef) : DTL FILE ERROR : Inconsistent length for font pathname:\n");
fprintf (stderr, "Recorded as ");
fprintf (stderr, UF4, a);
fprintf (stderr, " + ");
fprintf (stderr, UF4, l);
fprintf (stderr, " = ");
fprintf (stderr, UF4, a+l);
fprintf (stderr, ", but measured as ");
fprintf (stderr, UF4, al);
fprintf (stderr, "\n");
dexit (1);
}
return (s + 4*4 + 2*1 + al);
}
/* fontdef */
U4
preamble
#ifdef __STDC__
(FILE * dtl, FILE * dvi)
#else
(dtl, dvi)
FILE * dtl;
FILE * dvi;
#endif
/* read preamble from dtl, and write in dvi */
/* return number of bytes written */
{
U4 k1;
/* i[1] */
xferunsigned (1, dtl, dvi);
/* num[4] */
xferunsigned (4, dtl, dvi);
/* den[4] */
xferunsigned (4, dtl, dvi);
/* mag[4] */
xferunsigned (4, dtl, dvi);
/* k[1] : length of comment */
/* x[k] : comment string */
/* k1 = 1 + k */
k1 = xferlenstring (1, dtl, dvi);
return (1 + 3*4 + k1);
}
/* preamble */
int
postamble
#ifdef __STDC__
(FILE * dtl, FILE * dvi)
#else
(dtl, dvi)
FILE * dtl;
FILE * dvi;
#endif
/* read postamble from dtl, and write in dvi */
/* return number of bytes written */
{
postamble_address = dvi_written - 1;
/* p[4] : DVI address of previous bop command */
/* --- unsigned? --- or signed, as I assume? */
/* For, surely p should be -1 if the DVI file has NO bop? */
xfer_bop_address (dtl, dvi);
/* num[4] */
xferunsigned (4, dtl, dvi);
/* den[4] */
xferunsigned (4, dtl, dvi);
/* mag[4] */
xferunsigned (4, dtl, dvi);
/* l[4] */
xferunsigned (4, dtl, dvi);
/* u[4] */
xferunsigned (4, dtl, dvi);
/* s[2] */
xferunsigned (2, dtl, dvi);
/* t[2] */
xferunsigned (2, dtl, dvi);
return (6*4 + 2*2);
}
/* postamble */
int
post_post
#ifdef __STDC__
(FILE * dtl, FILE * dvi)
#else
(dtl, dvi)
FILE * dtl;
FILE * dvi;
#endif
/* read post_post from dtl, and write in dvi */
/* return number of bytes written */
{
/* hope I'm writing the "223" bytes in an 8-bit clean way */
int n223; /* number of "223" bytes in final padding */
/* q[4] : DVI address of post command */
/* --- unsigned? --- or signed, as I assume? */
/* what happens if there is NO postamble command? */
/* shouldn't q be -1 then? */
xfer_postamble_address (dtl, dvi);
/* i[1] : DVI identification byte = 2 */
xferunsigned (1, dtl, dvi);
/* final padding of DVI file by "223" bytes to a multiple of 4 bytes */
for (n223 = 0; true; n223++)
{
COUNT nread = 0; /* number of DTL bytes read by read_token */
Token token = "";
nread =
read_token (dtl, token);
/* check whether end of dtl file */
if (nread == 0)
{
if (group)
{
/* dtl file shouldn't end before an ECOM */
PRINT_PROGNAME;
fprintf (stderr,
"(post_post) : DTL FILE ERROR : premature end of DTL file!\n");
fprintf (stderr,
"%d complete iterations of \"padding byte\" loop \n",
n223);
fprintf (stderr,
"troublesome token = \"%s\"\n",
token);
dexit (1);
}
/* leave the "223" loop */
break;
}
else if (strcmp (token, "223") == 0)
{
/* token is a "223" padding byte */
putbyte (dvi, 223);
/* loop again */
}
else
{
/* read a non-empty token that wasn't "223" */
(Void) unread_char ();
if (group)
{
if (strcmp (token, ECOM) == 0)
{
/* end of post_post */
}
else
{
/* error : expected end of post_post */
PRINT_PROGNAME;
fprintf (stderr, "(post_post) : DTL FILE ERROR : ");
fprintf (stderr, "token \"%s\" should be \"%s\"\n", token, ECOM);
dexit (1);
}
}
/* leave the "223" loop */
break;
}
}
/* end for */
if (n223 < 4)
{
PRINT_PROGNAME;
fprintf (stderr, "(post_post) : DTL FILE ERROR : bad post_post: ");
fprintf (stderr, "fewer than four `223' bytes.\n");
dexit (1);
}
/* check whether the DVI file size is a multiple of 4 bytes */
if (dvi_written % 4 != 0)
{
PRINT_PROGNAME;
fprintf (stderr, "(post_post) : DTL FILE (OR INTERNAL) ERROR : ");
fprintf (stderr, "DVI size ");
fprintf (stderr, WF, dvi_written);
fprintf (stderr, " (bytes) isn't a multiple of 4 !\n");
dexit (1);
}
return (4 + 1 + n223);
}
/* post_post */
Void
dinfo (VOID)
{
PRINT_PROGNAME;
fprintf (stderr, "(dinfo) : ");
fprintf (stderr, "Current DTL input line:\n");
fprintf (stderr, "\"%s\"\n", dtl_line.buf);
fprintf (stderr, "Read ");
fprintf (stderr, WF, dtl_read);
fprintf (stderr, " DTL bytes (");
fprintf (stderr, WF, com_read);
fprintf (stderr, " in current command), wrote ");
fprintf (stderr, WF, dvi_written);
fprintf (stderr, " DVI bytes.\n");
fprintf (stderr, "Successfully interpreted ");
fprintf (stderr, WF, ncom);
fprintf (stderr, " DVI command%s.\n", (ncom == 1 ? "" : "s"));
}
/* dinfo */
Void
dexit
#ifdef __STDC__
(int n)
#else
(n)
int n;
#endif
{
dinfo();
PRINT_PROGNAME;
fprintf (stderr, "(dexit) : exiting with status %d.\n", n);
exit (n);
}
/* dexit */
/* end of dt2dv.c */